<?php

/**
 * Library :: Widget :: Recordset
 *
 * Warlock is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 *
 * @package    warlock
 * @author     David Cole <neophyte@sourcetutor.com>
 * @license    GNU/GPL v2
 */

class RecordSet extends Object
{
    var $_ID;
    var $_Title;
    var $_DataObject;
    var $_Where;
    var $_Order;
    var $_PerPage;
    var $_Fields;
    var $_Actions;
    var $_Filters;
    var $_SearchFields;
    var $_CurrentPage;
    var $_SearchString;
    var $_URI;

    /**#@+
     * Required Core Objects
     *
     * These are references to the core objects required by this
     * class.
     *
     * @access private
     * @var    object
     */
    var $_Error;
    var $_Profiler;
    var $_DAL;
    var $_Model;
    /**#@-*/

    /**
     * Constructor
     *
     * @param string $id        Unique ID for the recordset
     * @param string $title     Title given for the recordset
     * @param string $do        DataObject from which data should be retrieved
     * @param string $perpage   Default number of results to display per page
     * @param array  $where     An array of where conditions to be passed to the DataObject
     * @param array  $order     An array of field => order pairs to be passwed to the DataObject
     *
     * @return void
     * @access public
     */
    function __construct($uri, $id, $title, $do, $perpage = 20, $where = array(), $order = array())
    {
        // Get References to required objects
        $this->_Error    = &Vault::Get('Debug_Error');
        $this->_Profiler = &Vault::Get('Debug_Profiling');
        $this->_DAL      = &Vault::Get('DAL');
        $this->_Model    = &Vault::Get('Model');

        // Set recordset properties/defaults
        $this->_ID           = $id;
        $this->_Title        = $title;
        $this->_DataObject   = $do;
        $this->_PerPage      = $perpage;
        $this->_Where        = $where;
        $this->_Order        = $order;
        $this->_SearchString = '';
        $this->_CurrentPage  = 1;
        $this->_URI          = $uri;
    }

    function AddField($field, $label, $width = false, $callback = false, $filter = false)
    {
        $this->_Fields[] = array('field'    => $field,
                                 'label'    => $label,
                                 'width'    => $width,
                                 'callback' => $callback);
    }

    function AddFilter($field, $title, $do, $value, $label)
    {
    	$this->_Filters[] = array('field'    => $field,
    	                          'title'    => $title,
    	                          'do'       => $do,
    	                          'value'    => $value,
    	                          'label'    => $label,
    	                          'selected' => '');
    }
    
    function AddAction($name, $label, $callback)
    {
        $this->_Actions[] = array('name'     => $name,
                                  'label'    => $label,
                                  'callback' => $callback);
    }

    function SearchFields()
    {
        $this->_SearchFields = func_get_args();
    }

    function Process()
    {
    		
	        /*
	         * Find out if the user clicked anything relating to this recordset and
	         * update the recordset and perform any actions as needed.
	         */        
	  
	        if (($_SERVER['REQUEST_METHOD'] == 'POST') && isset($_POST[$this->_ID]))
	        {
	            /*
	             * Check if the user clicked on one of the 
	             * action buttons.
	             */               
	
	            for ($i = 0, $imax = count($this->_Actions); $i < $imax; $i++)   
	            {                 
	                if (($this->_Actions[$i]['name'] == $_POST[$this->_ID]) && is_callable($this->_Actions[$i]['callback']))
	                {
	                	$_POST[$this->_ID] = false; // Stop the action being called recursively if process is called again
	                    call_user_func($this->_Actions[$i]['callback'], $_POST['rs_'.$this->_ID.'_selected']);
	                    return true;
	                }
	            }
	            
	            /*
	             * Look over the post data to grab any search strings, page numbers etc
	             */
	            
	            // Selected Page
	            if (isset($_POST[$k = ('rs_'.$this->_ID.'_page')]) && is_numeric($_POST[$k = ('rs_'.$this->_ID.'_page')]))
	                $this->_CurrentPage = $_POST[$k];
	
	            // Search String
	            if (isset($_POST[$k = ('rs_'.$this->_ID.'_query')]))
	                $this->_SearchString = $_POST[$k];
	                
	            // Filters
	            for ($i = 0, $imax = count($this->_Filters); $i < $imax; $i++)
	                if(isset($_POST[$k = ('rs_'.$this->_ID.'_'.$this->_Filters[$i]['field'])]) && (strlen($_POST[$k]) > 0))
	                    $this->_Filters[$i]['selected'] = $_POST[$k];
	                    
	            /*
	             * Display recordset with the updated settings
	             */
	            
	            $this->_Model->Body('library', $this->ToArray(), $this->_ID, 'recordset');
	            return true;             
	        }
	        else 
	        {
	            /*
	             * Display the recordset using the known defaults
	             */
	            
	            $this->_Model->Body('library', $this->ToArray(), $this->_ID, 'recordset');
	            return true;            
	        }
    	    	
    }
    
    function ToArray()
    {
        /*
         * Work out the offset to user
         */

        $offset = ($this->_CurrentPage - 1) * $this->_PerPage;
        
        /*
         * Add any set filters to the where clause
         */
        
        for ($i = 0, $imax = count($this->_Filters); $i < $imax; $i++)
            if (strlen($this->_Filters[$i]['selected']) > 0)
                $this->_Where[$this->_Filters[$i]['field']] = $this->_Filters[$i]['selected'];

        /*
         * Generate the array of results to be displayed
         */

        $data  = array();
        $rs    = $this->_DAL->Select($this->_DataObject, $this->_Where, $this->_Order, $this->_PerPage, $offset, 'ASSOC');        
        
        $total = $rs->Count();

        while ($r = $rs->FetchRow())
        {
            $temp = array();
            
            for ($i = 0, $max = count($this->_Fields); $i < $max; $i++)
                $temp[] = is_callable($this->_Fields[$i]['callback'])?call_user_func($this->_Fields[$i]['callback'], $r):$r[$this->_Fields[$i]['field']];
        
            $data[] = $temp;
        }

        /*
         * Generate Array of Filters
         */
        
        $filters = array();
        
        for ($i = 0, $imax = count($this->_Filters); $i < $imax; $i++)
        {
        	$rs = $this->_DAL->Select($this->_Filters[$i]['do']);
			$filters[$this->_Filters[$i]['field']] = array();
        	
        	while ($r = $rs->FetchRow('ASSOC'))
        	{
        		$filters[$this->_Filters[$i]['field']]['title']  = $this->_Filters[$i]['title'];
        		$filters[$this->_Filters[$i]['field']]['data'][] = array('value'    => $r[$this->_Filters[$i]['value']],
        		                                                         'label'    => $r[$this->_Filters[$i]['label']],
        		                                                         'selected' => (($r[$this->_Filters[$i]['value']] == $this->_Filters[$i]['selected'])?'yes':'no'));
        	}
        }
        
        /*
         * Generate the return array which will be used to display
         * the resultset.
         */

        $return = array();

        // General Recordset Info
        $return['summary'] = array('uri'         => $this->_URI,
                                   'id'          => $this->_ID,
                                   'title'       => $this->_Title,
                                   'perpage'     => $this->_PerPage,
                                   'total_rows'  => $total,
                                   'total_pages' => ceil($total / $this->_PerPage),
                                   'page'        => (($offset / $this->_PerPage) + 1));

        // Fields for which the user can filter the recordset                                         
        $return['filters'] = $filters;                                   
                                   
        // Recordset Field to Display                                   
        $return['fields']  = $this->_Fields;       
        
        // Actions allowed to be performed upon each of the records
        for ($i = 0, $imax = count($this->_Actions); $i < $imax; $i++)
            $return['actions'][] = array('name'  => $this->_Actions[$i]['name'],
                                         'label' => $this->_Actions[$i]['label']);
        
        
        // Recordset Data
        $return['data']    = $data;

        return $return;
    }
}

?>